/*****************************************************************************************
 * FILE NAME: srv_chaodian_can                                     COPYRIGHT (c) TX 2025
 * REVISION:  1.0.0                                     All Rights Reserved
 * DESCRIPTION: 超电CAN协议模块 - 简化版
 * =======================================================================================
 * UPDATE HISTORY：
 * REV      AUTHOR      DATE
 * v1.0.0   fangangchuan  2025.10.15
 * DESCRIPTION OF CHANGE: 基于超电测试协议文档实现简化的CAN协议模块
 ****************************************************************************************/
#ifndef __SRV_CD_CAN_L_H
#define __SRV_CD_CAN_L_H

//----------------------------------------------------------------------------------------
// @Project Includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>

//----------------------------------------------------------------------------------------
// @Global Macro Define in the module

/* 超电CAN协议相关定义 */
#define CD_CAN_PROTOCOL_VERSION    0x0100    // 协议版本 1.0

/* 设备地址定义 */
#define CD_DEVICE_ADDR_HOST        0x0A      // 上位机
#define CD_DEVICE_ADDR_BMS         0x0B      // BMS
#define CD_DEVICE_ADDR_CHARGER     0x0C      // 充电机

/* 功能码定义 */
#define CD_FUNC_READ_REG           0x03      // 读寄存器
#define CD_FUNC_WRITE_REG          0x10      // 写寄存器
#define CD_FUNC_READ_REG_ERROR     0x83      // 读寄存器错误
#define CD_FUNC_WRITE_REG_ERROR    0x90      // 写寄存器错误
#define CD_FUNC_EVENT_REPORT       0x64      // 事件上报

/* CAN ID 掩码和偏移 */
#define CD_CAN_ID_FUNC_MASK        0xFF000000UL
#define CD_CAN_ID_FUNC_SHIFT       24
#define CD_CAN_ID_REG_MASK         0x00FFFF00UL
#define CD_CAN_ID_REG_SHIFT        8
#define CD_CAN_ID_DST_MASK         0x000000F0UL
#define CD_CAN_ID_DST_SHIFT        4
#define CD_CAN_ID_SRC_MASK         0x0000000FUL
#define CD_CAN_ID_SRC_SHIFT        0

/* CAN ID 构建宏 */
#define CD_BUILD_CAN_ID(func, reg_addr, dst_addr, src_addr) \
    (((func) << CD_CAN_ID_FUNC_SHIFT) | \
     ((reg_addr) << CD_CAN_ID_REG_SHIFT) | \
     ((dst_addr) << CD_CAN_ID_DST_SHIFT) | \
     ((src_addr) << CD_CAN_ID_SRC_SHIFT))

/* 数据填充值 */
#define CD_DATA_FILL               0xFF

/* 特殊寄存器组定义 */
#define CD_REG_RESET               (11)    // 复位寄存器
#define CD_REG_FACTORY_RESET       (12)    // 恢复出厂设置寄存器
#define CD_REG_CLEAR_USER_DATA     (13)    // 清除用户数据寄存器

#define CD_REG_UPGRADE_START       (300)    // 开始升级寄存器
#define CD_REG_RUN_APP             (301)    // 直接运行app寄存器
#define CD_REG_ENTER_UPGRADE_MODE  (302)    // 请求进入升级模式寄存器
#define CD_REG_FIRMWARE_SIZE       (303)    // 升级包大小寄存器
#define CD_REG_FIRMWARE_CRC        (305)    // 升级包CRC寄存器
#define CD_REG_DOWNLOAD_FIRMWARE   (315)    // 下发固件数据寄存器

/* 最大寄存器数量 */
#define CD_MAX_REG_COUNT           255
#define CD_MAX_FRAME_COUNT         255

/* 多帧传输相关 */
#define CD_MULTI_FRAME_TIMEOUT_MS  200    // 多帧传输超时时间(毫秒)
#define CD_MAX_MULTI_FRAME_SIZE    (2*CD_MAX_REG_COUNT)   // 最大多帧数据大小

/* 升级相关 */
#define CD_UPGRADE_STATE_IDLE      0x00   // 空闲状态
#define CD_UPGRADE_STATE_PREPARE   0x01   // 准备状态
#define CD_UPGRADE_STATE_RECEIVE   0x02   // 接收状态
#define CD_UPGRADE_STATE_VERIFY    0x03   // 验证状态
#define CD_UPGRADE_STATE_COMPLETE  0x04   // 完成状态
#define CD_UPGRADE_STATE_ERROR     0xFF   // 错误状态

#define CD_MAX_FIRMWARE_SIZE       512*1024  // 最大固件大小 512KB
#ifndef CD_UPGRADE_TIMEOUT_MS
#define CD_UPGRADE_TIMEOUT_MS       10000     // 升级超时时间 10秒
#endif

/* 错误码定义 */
#define CD_ERROR_SUCCESS           0x00      // 成功
#define CD_ERROR_ILLEGAL_FUNC      0x01      // 非法功能
#define CD_ERROR_ILLEGAL_ADDR      0x02      // 非法数据地址
#define CD_ERROR_ILLEGAL_VALUE     0x03      // 非法数据值
#define CD_ERROR_SLAVE_FAILURE     0x04      // 从站设备故障
#define CD_ERROR_ACKNOWLEDGE       0x05      // 确认
#define CD_ERROR_SLAVE_BUSY        0x07      // 从属设备忙
#define CD_ERROR_CHECKSUM_ERROR    0x08      // 校验码错误

/* 寄存器权限定义 */
#define CD_REG_PERM_READ_ONLY      0x01      // 只读
#define CD_REG_PERM_WRITE_ONLY     0x02      // 只写
#define CD_REG_PERM_READ_WRITE     0x03      // 读写

/* 数据类型定义 */
#define CD_DATA_TYPE_UINT8         0x01      // uint8
#define CD_DATA_TYPE_UINT16        0x02      // uint16
#define CD_DATA_TYPE_UINT32        0x03      // uint32
#define CD_DATA_TYPE_STRING        0x04      // string

//----------------------------------------------------------------------------------------
// @Global Type defines in the module

/* 数据转换函数类型定义 */
// 统一的转换函数类型定义
typedef uint8_t (*cd_data_transform_func_t)(uint8_t operation, const void *raw_data, uint8_t *data, uint8_t len);

// 转换操作类型定义
#define CD_TRANSFORM_READ    0    // 读取操作
#define CD_TRANSFORM_WRITE   1    // 写入操作

/* 寄存器映射表项 - 超紧凑版本，进一步减少RAM占用 */
typedef struct
{
    uint16_t reg_addr;                    // 寄存器地址
    uint16_t flags;                       // 组合标志位：permission(2) + data_type(3) + data_size(11)
    void *data_ptr;                       // 数据指针
    cd_data_transform_func_t transform_func;             // 统一的数据转换函数
} stc_cd_reg_map_t;

/* 标志位操作宏定义 */
#define CD_REG_FLAGS_PERM_MASK      0x0003    // 权限掩码
#define CD_REG_FLAGS_TYPE_MASK      0x001C    // 数据类型掩码
#define CD_REG_FLAGS_SIZE_MASK      0xFFE0    // 数据大小掩码（寄存器数量）

// 寄存器标志位宏定义
// size参数表示寄存器数量（1个寄存器=2字节）
#define CD_REG_SET_FLAGS(perm, type, size) \
    (((perm) & 0x03) | (((type) & 0x07) << 2) | (((size) & 0x7FF) << 5))

#define CD_REG_GET_PERM(flags)      ((flags) & CD_REG_FLAGS_PERM_MASK)
#define CD_REG_GET_TYPE(flags)      (((flags) & CD_REG_FLAGS_TYPE_MASK) >> 2)
#define CD_REG_GET_SIZE(flags)      (((flags) & CD_REG_FLAGS_SIZE_MASK) >> 5)  // 返回寄存器数量

/* CAN消息结构体 */
typedef struct
{
    uint8_t func_code;                    // 功能码
    uint16_t reg_count;                   // 寄存器数量
    uint8_t frame_index;                  // 帧索引
    uint8_t data[4];                      // 数据内容(最多4字节)
} stc_cd_can_msg_t;

/* 多帧传输管理结构体 */
typedef struct
{
    uint32_t can_id;                       // CAN ID
    uint16_t reg_addr;                     // 起始寄存器地址
    uint16_t reg_count;                    // 寄存器总数
    uint8_t total_frames;                  // 总帧数
    uint8_t current_frame_idx;             // 当前帧索引
    uint8_t *data_buffer;                  // 数据缓冲区
    uint16_t buffer_size;                  // 缓冲区大小
    uint32_t last_update_tick;             // 最后更新时间
    uint8_t active;                        // 是否激活
    uint8_t func_code;                     // 功能码
} stc_cd_multi_frame_t;

/* 升级管理结构体 */
typedef struct
{
    uint8_t upgrade_state;                 // 升级状态
    uint32_t firmware_size;                // 固件大小
    uint16_t firmware_crc;                 // 固件CRC校验
    uint32_t received_size;                 // 已接收大小
    uint8_t *firmware_buffer;              // 固件数据缓冲区
    uint32_t buffer_size;                  // 缓冲区大小
    uint32_t last_data_tick;               // 最后数据接收时间
    uint8_t active;                        // 是否激活
} stc_cd_upgrade_t;

/* 超电CAN协议模块结构体 */
typedef struct
{
    uint8_t device_addr;                  // 本设备地址
    uint8_t protocol_version;             // 协议版本
    
    /* 多帧传输管理 */
    stc_cd_multi_frame_t multi_frame_rx;  // 接收多帧
    stc_cd_multi_frame_t multi_frame_tx;  // 发送多帧
    
    /* 升级管理 */
    stc_cd_upgrade_t upgrade;
    
    /* 统计信息 */
    struct {
        uint32_t rx_count;                // 接收计数
        uint32_t tx_count;                // 发送计数
        uint32_t error_count;             // 错误计数
        uint32_t timeout_count;           // 超时计数
    } stats;
    
} stc_cd_can_t;

//----------------------------------------------------------------------------------------
// @Export global Variables declare in the module
extern stc_cd_can_t g_stcCdCan;

//----------------------------------------------------------------------------------------
// @Export declaration of functions in the module

/* 数据转换函数 */
uint8_t cd_transform_speed(uint8_t operation, const void *raw_data, uint8_t *data, uint8_t len);
uint8_t cd_transform_gps_speed_limit(uint8_t operation, const void *raw_data, uint8_t *data, uint8_t len);

/* 基础工具函数 */
uint32_t cd_can_build_id(uint8_t func_code, uint16_t reg_addr, uint8_t dst_addr, uint8_t src_addr);
uint8_t cd_can_parse_id(uint32_t can_id, uint8_t *func_code, uint16_t *reg_addr, uint8_t *dst_addr, uint8_t *src_addr);
uint8_t cd_can_is_for_me(uint32_t can_id, uint8_t my_addr);
const stc_cd_reg_map_t* cd_can_find_reg_map(uint16_t reg_addr);

/* 数据读写函数 */
uint8_t cd_can_read_data_from_ptr(const stc_cd_reg_map_t *reg_map, uint8_t *data, uint8_t max_len);
uint8_t cd_can_write_data_to_ptr(const stc_cd_reg_map_t *reg_map, uint8_t *data, uint8_t len);

uint8_t cd_can_is_reg_readable(uint16_t reg_addr);
uint8_t cd_can_is_reg_writable(uint16_t reg_addr);

/* 发送响应函数 */
uint8_t cd_can_send_read_response(uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t *data, uint8_t error_code);
uint8_t cd_can_send_write_response(uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t error_code);
uint8_t cd_can_send_error_response(uint8_t func_code, uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t error_code);
uint8_t cd_can_send_event_report(uint16_t reg_addr, uint8_t *data);
void cd_can_send_multi_frame_data(uint16_t reg_addr, uint16_t reg_count, uint8_t *data, uint16_t data_len, uint8_t func_code);

/* 写入处理函数 */
uint8_t cd_can_process_single_frame_write(uint16_t reg_addr, uint16_t reg_count, uint8_t *data);
uint8_t cd_can_write_multi_register_range(uint16_t start_addr, uint16_t reg_count, uint8_t *data_buffer);
uint8_t cd_can_process_multi_frame_write(uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t *data);

/* 消息处理函数 */
void cd_can_process_read_request(uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t *data);
void cd_can_process_write_request(uint16_t reg_addr, uint16_t reg_count, uint8_t frame_index, uint8_t *data);
void cd_can_process_upgrade_message(uint16_t reg_addr, uint8_t *data);

/* 升级相关函数 */
uint8_t cd_can_start_upgrade(uint32_t firmware_size, uint16_t firmware_crc);
uint8_t cd_can_process_upgrade_data(uint8_t *data, uint8_t length);
uint8_t cd_can_finish_upgrade(void);
uint8_t cd_can_get_upgrade_state(void);

/* 统计信息函数 */
void cd_can_get_stats(uint32_t *rx_count, uint32_t *tx_count, uint32_t *error_count, uint32_t *timeout_count);
void cd_can_reset_stats(void);

/* 对外接口函数 */
void cd_can_init(uint8_t device_addr);
void cd_can_process_message(uint32_t can_id, uint8_t *data, uint8_t length);
void cd_can_task(void);

#endif

// =======================================================================================
// End of file.
// =======================================================================================